Day26 要來做個有下拉選單的導覽列
const navItems: NavItem[] = [
{ name: "About", dropdown: ["Team", "History", "Contact"] },
{ name: "Services", dropdown: ["Design", "Development", "Consulting"] },
{ name: "Contact", dropdown: ["Email", "Phone", "Location"] },
];
const [activeDropdown, setActiveDropdown] = useState<number | null>(null);
const [dropdownStyles, setDropdownStyles] = useState<DropdownStyles>({});
const navRef = useRef<HTMLElement | null>(null);
const backgroundRef = useRef<HTMLDivElement | null>(null);
const handleMouseEnter = useCallback(
(e: React.MouseEvent<HTMLLIElement>, index: number) => {
const dropdown = (e.target as HTMLElement).querySelector(".dropdown");
if (!dropdown || !navRef.current) {
return;
}
setActiveDropdown(index);
const navBounds = navRef.current.getBoundingClientRect();
const dropdownBounds = dropdown.getBoundingClientRect();
const styles: DropdownStyles = {
width: `${dropdownBounds.width}px`,
height: `${dropdownBounds.height}px`,
transform: `translate(${dropdownBounds.left - navBounds.left}px, ${
dropdownBounds.top - navBounds.top
}px)`,
};
setDropdownStyles(styles);
},
[]
);
const handleMouseLeave = useCallback(() => {
setActiveDropdown(null);
}, []);
return (
<nav ref={navRef} className="relative p-4 bg-white shadow-md">
<div
ref={backgroundRef}
className="absolute bg-white transition-all duration-150 ease-out opacity-0"
style={{
...dropdownStyles,
opacity: activeDropdown !== null ? 1 : 0,
visibility: activeDropdown !== null ? "visible" : "hidden",
}}
/>
<ul className="flex space-x-4">
{navItems.map((item, index) => (
<li
key={item.name}
className="relative"
onMouseEnter={(e) => handleMouseEnter(e, index)}
onMouseLeave={handleMouseLeave}
>
<a href="#" className="text-gray-700 hover:text-gray-900">
{item.name}
</a>
<div
className={`dropdown absolute left-0 top-full mt-2 w-48 bg-white shadow-lg rounded-md overflow-hidden transition-all duration-150 ease-out ${
activeDropdown === index
? "opacity-100 visible"
: "opacity-0 invisible"
}`}
>
<ul className="py-2">
{item.dropdown.map((subItem) => (
<li key={subItem}>
<a
href="#"
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
>
{subItem}
</a>
</li>
))}
</ul>
</div>
</li>
))}
</ul>
</nav>
);